package com.jacobson.core.framework

import android.content.Context
import android.content.pm.PackageManager

/**
 * ================================================
 * 从 ***AndroidManifest.xml***文件中读取APP配置类
 * @see AppConfiguration
 * @author Wucz on 2018/7/18 14:37
 * ================================================
 */

class AndroidManifestParser(
        val context: Context
) {
    fun parse(): MutableList<AppConfiguration> {
        val configs = mutableListOf<AppConfiguration>()
        try {
            context.run {
                packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA)?.run {
                    metaData.keySet().forEach {
                        if (APP_CONFIGURATION_VALUE == metaData.get(it)) {
                            configs.add(parseAppConfiguration(it))
                        }
                    }
                }

            }
        } catch (e: PackageManager.NameNotFoundException) {
            throw RuntimeException("Unable to find metadata to Parse AppConfiguration")
        }
        return configs
    }

    private fun parseAppConfiguration(className: String): AppConfiguration {
        try {
            Class.forName(className).run {
                newInstance()?.let {
                    (it as AppConfiguration).run {
                        return this
                    }
                }
            }
        } catch (e: ClassNotFoundException) {
            throw IllegalArgumentException("Unable to find AppConfiguration implementation", e)
        } catch (e: InstantiationException) {
            throw RuntimeException("Unable to instantiate AppConfiguration implementation for $className", e)
        } catch (e: IllegalAccessException) {
            throw RuntimeException("Unable to instantiate AppConfiguration implementation for $className", e)
        } catch (e: Exception) {
            throw RuntimeException("Unable to instantiate AppConfiguration implementation for $className", e)
        }
        throw RuntimeException("Unable to instantiate AppConfiguration implementation for $className")
    }

    companion object {
        const val APP_CONFIGURATION_VALUE: String = "AppConfiguration"
    }
}